from picshell.engine.core.PicEngine import PicEngine
from picshell.engine.core.PicThreadEngine import PicThreadEngine
from picshell.engine.util.Format import Format
from picshell.monitors.DeviceStateMonitors import DeviceSourceStateMonitor
from picshell.monitors.DeviceStateMonitors import DeviceTargetStateMonitor
from picshell.monitors.RegisterUpdater import RegisterUpdater
from picshell.parser.AnnotationParser import AnnotationParser
from picshell.parser.JalV2AsmParser import JalV2AsmParser
from picshell.parser.JalV2Parser import JalV2Parser
from picshell.ui.Context import Context
from picshell.ui.config.PreferencesDialog import PreferencesDialog
from picshell.ui.debug.comp.CLED import CLED
from picshell.ui.debug.comp.Counter import UpDownCounter
from picshell.ui.debug.comp.Dual7Seg import Dual7Seg
from picshell.ui.debug.comp.LCD import LCD
from picshell.ui.debug.comp.StaticText import StaticText
from picshell.ui.debug.comp.LED import LED
from picshell.ui.debug.comp.Watch import Watch
from picshell.ui.edit.EditorUtil import EditorUtil
from picshell.ui.edit.FindDialog import FindDialog
from picshell.util.AssertUtil import AssertUtil
from picshell.util.DocHelper import AsmDocHelp
from picshell.util.FileUtil import FileUtil
from picshell.modules.Validate.JSGValidator import JSGValidator
from picshell.engine.core.pics import PicFactory
from wx._gdi import HOURGLASS_CURSOR
from wx._gdi import STANDARD_CURSOR
from wx.stc import STC_EOL_CRLF
import  wx.lib.newevent
from zipfile import ZipFile
import zipfile
import JALsPy_globals
import os
import platform
import re
import subprocess
import sys
import time
import wx


class UIManager:
    MY_EVT_CALLBACK = None
    (UpdateCallbackEvent, MY_EVT_CALLBACK) = wx.lib.newevent.NewEvent()

    devices = []
    def __init__(self):
        
        self.debugView= None
        self.editView = None
        self.browserView = None
        
        self.mainSplitter = None
        self.tabEditMaximized = False
        self.tabBrowserMaximized = False
        self.mainEditor = None
        self.browserEditor = None
        self.browserSplitter = None
        self.outLineTree = None
        self.outLineSearch = None
        self.compileTab = None
        self.listAsm = None
        self.listLang = None
        self.listResult = None
        self.listUnitTest = None
        self.listBreakpoint = None
        self.compileLog = None
        self.helpText = None
        self.inOutPanel = None
        self.inOutSizer = None
        
        self.bottomSplitter = None # debug view
        self.topSplitter = None # debug view
        
        
        self.bNextLang = None
        self.bNextAsm = None
        self.drawWindow = None
        self.explainAsmText = None
        self.fixedMark = None
        self.deepSearchText = None
        self.deepSearchTree = None
        self.browserSplitter = None
        self.searchInComment = None
        
        
        self.needClose = False
        self.hexFileName = None
        self.statusBar = None
        self.top = None
        self.tab = None
        self.varTypeDict = None
        self.emu = None
        self.threadEngine = None
        self.plugins = []
        self.nodesForAddress = [0]*1024*128
        self.devicesForAddressRead = [0]*1024*128
        self.devicesForAddressWrite = [0]*1024*128

        self.picName = ""
        
        for i in range(0,1024*128):
            self.nodesForAddress[i] = None
            self.devicesForAddressRead[i] = None
            self.devicesForAddressWrite[i] = None

        self.running = False
        self.breakpoints = {}
#        self.breakpoints = [0] * 1024*128
#        for i in range(0,1024*128):
#            self.breakpoints[i] = False      
        
   
    def newProject(self):
        self.stop()
        self.top.toolbar.EnableTool(Context.TOOL_RUN,False)
        self.top.GetMenuBar().Enable(124,False)
        
        self.top.toolbar.EnableTool(Context.TOOL_RUN_UNIT_TEST,False)
        
        self.top.toolbar.EnableTool(Context.TOOL_OPEN,True)
        self.top.toolbar.EnableTool(Context.TOOL_NEW,True)
        self.top.GetMenuBar().Enable(100,True)
        self.top.GetMenuBar().Enable(101,True)
        self.top.GetMenuBar().Enable(103,True)
        
        self.varTypeDict = None
        self.running = False
        self.emu = None
        self.debugView.Clear()
        self.threadEngine = None
        
        self.breakpoints = {}
        self.mainEditor.SetText("")
        self.mainEditor.filename=""
        self.hexFileName = None
        self.browserEditor.SetText("")
        self.browserEditor.filename=""
        self.tab.SetPageText(1,"Main file")
        self.tab.SetPageText(2,"Include viewer")
        self.outLineTree.DeleteAllItems()
        self.listAsm.DeleteAllItems()
        self.listLang.DeleteAllItems()
        self.listResult.DeleteAllItems()
        self.inOutPanel.DestroyChildren()
        self.compileLog.Clear()
        self.plugins = []
        self.browserView.clearBrowerTree()
   
    def compileProjectAlternate(self):
        self.compileProject(Context.compiler2,Context.libpath2,Context.compiler2Options)
        
    def startProgrammer(self):
        options = Context.programmerOptions
        options = options.replace("%jal",self.mainEditor.filename)
        options = options.replace("%hex",self.mainEditor.filename.replace(".jal",".hex"))
        options = options.replace("%asm",self.mainEditor.filename.replace(".jal",".asm"))
        options = options.replace("%F",self.mainEditor.filename.replace(".jal",""))
        os.system(Context.programmer+" "+options )

    def getPicName(self):
        picName = "16f877a"
        
        search_paths = FileUtil.expand_paths( Context.libpath +";"+os.path.dirname(self.mainEditor.filename) )
        files =[self.mainEditor.filename]
        files += list(EditorUtil.findAllIncludesWithPath(self.mainEditor.GetText(),search_paths))

        for filename in files:
           # print "CHECK FILE "+filename
           file = open (filename)
           num = 0
           for lg in file:
              lg = (lg.lstrip()).rstrip()              
              lg.replace( ";","--")				

              p1 = lg.find( "pragma" )
              if p1 >= 0 :
                 p2 = lg.find( "target" )
                 if ( p2 > p1 ):
                    p3 = lg.find( "chip" )
                    if ( p3 > p2 ):                 	
                       p0 = lg.find( "--" )
                       if ( p0 < 0 ) or ( p0 > p3) :
                          lg = lg[ p3 + len("chip"): ]
                          p0 = lg.find( " " )
                          if p0 > 0:
                             lg = lg[:p0]
                          picName = (lg.lstrip()).rstrip()
                          # print "PICNAME  :" + picName + ":"   
           file.close()
        # print "Got Picname " + picName
        self.picName = picName               

    def HandleCompilerErrorResults(self, outputlines):
           #
           # handle result
           #
           i = 0
           hasErrors = True
           message = ""
           for lg in outputlines:
            
                message += lg
                
                if lg.startswith("0 error") :
                    hasErrors = False
                elif ".jal" in lg:
                    try :
                        lg = lg.strip()
                        
                        lineNum =""
                        filename =""
                        msg =""
                        part = 0
                        for c in lg :
                            if c == ':' and len(filename) > 1:
                                part += 1
                            elif part == 0 :
                                filename += c
                            elif part == 1 :
                                lineNum += c
                            if part > 1:
                                msg += c
                        msg = msg[1:]
                        
                        self.listResult.InsertStringItem(i,lineNum )
                        self.listResult.SetStringItem(i,1,  filename)
                        self.listResult.SetStringItem(i,2, msg )
                        
                        if self.mainEditor.filename == filename:
                            try :
                                self.mainEditor.markLineError(int(lineNum)-1) # error is 1 based
                            except : pass
                        elif  self.browserEditor.filename == filename:
                            try :
                                self.browserEditor.markLineError(int(lineNum)-1) # error is 1 based
                            except : pass
                        else:
                            self.listResult.SetItemTextColour(i,"#A0A0A0")    
                        i += 1
                    except : pass
           self.compileLog.AppendText(message)
           return hasErrors
   
    def compileProject(self,compiler,libpath,options):
       self.top.SetCursor(HOURGLASS_CURSOR)
       
       options = options.strip()
       if compiler=="":
           compiler = Context.compiler
       if libpath=="":
            libpath = Context.libpath
            
       
       if (self.mainEditor.filename != "") and not self.mainEditor.filename.endswith("*"):
           
           if self.mainEditor.filename.endswith(".txt"):
               #parseRes = AnnotationParser.parse(self.mainEditor.GetText())
               #self.buildInOut(parseRes["inputs"],parseRes["outputs"])
               self.importHex(self.mainEditor.filename.replace(".txt",".hex"))
               self.compileLog.AppendText("I/O Updated")
               return
           
           
           self.listResult.DeleteAllItems()
           self.compileLog.Clear()
           
           #clean indicator
           for i in range(0,self.mainEditor.GetLineCount()):
                   self.mainEditor.unMarkLine(i)
           
           
           # AF look for better solution 
           # need to update FSR regs in format
           self.getPicName()
           self.pic = PicFactory( "pic_" + self.picName )           
           Format.spReg = self.pic.fsr_regs

           parseRes = AnnotationParser.parse(self.mainEditor.GetText())
           anno_options = parseRes["options"]

           libpath = FileUtil.expand_paths( libpath )
           
           vlibpath = None
           if "virtual_delay" in anno_options :
               # these files will shortcut real  files in virtual mode...
               vpath =  os.path.abspath(".")+os.sep+"virtual"
               vlibpath =vpath+";"+libpath
           
           #
           # Start compiler
           #
           arguments = [os.path.expandvars( os.path.expanduser( compiler ) ) ]
           varguments = [os.path.expandvars( os.path.expanduser( compiler ) ) ]
           opt = options.split(" ")
           if (opt!= None) and len(opt)>0 and options!= "":
              arguments+=opt
              varguments +=opt
           
           self.hexFileName = self.mainEditor.filename.replace(".jal",".hex")
           virtualHexFileName = self.buildVirtualFileName(self.hexFileName)
           arguments+=["-s",libpath,self.mainEditor.filename]
           
           self.compileLog.AppendText("Compilation line is : ")
           for arg in arguments:
               self.compileLog.AppendText(arg+" ")
           self.compileLog.AppendText("\n")
           if wx.Platform == '__WXMSW__':
               p = subprocess.Popen(args=arguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
           else :
               p = subprocess.Popen(args=arguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False)
               
           outputlines = p.stdout.readlines()
           p.wait()
           
           
           # clear breakpoints
           self.removeAllBreakpoints()


           hasErrors = self.HandleCompilerErrorResults(outputlines)

           if (hasErrors):
               self.tab.SetSelection(Context.TAB_EDIT) # goto edit tab
               self.top.GetStatusBar().SetStatusText("Compile status : Errors")
               self.listAsm.DeleteAllItems()
               self.listLang.DeleteAllItems()
               self.compileTab.SetSelection(Context.COMPILE_ERROR_TAB) 
               self.top.toolbar.EnableTool(Context.TOOL_RUN,False)
               self.top.GetMenuBar().Enable(124,False)
               self.top.toolbar.EnableTool(Context.TOOL_RUN_UNIT_TEST,False)


           else:
                #update list, use the parsers...
               self.compileTab.SetSelection(Context.COMPILE_RESULT_TAB)
               self.top.GetStatusBar().SetStatusText("Compile status : Ok")
               
               noDebugList = parseRes["noDebug"] 
               debugList =parseRes["debug"]  
               
               if parseRes["regfilter"] != "":
                   self.debugView.regFilter.SetLabel(parseRes["regfilter"])
               if parseRes["varfilter"] != "":
                   self.debugView.varFilter.SetLabel(parseRes["varfilter"])
                
               asmFileName = self.mainEditor.filename.replace(".jal",".asm")   
               if "virtual_delay" in anno_options :
                   asmFileName = self.buildVirtualFileName(asmFileName)
                   self.compileLog.AppendText("\nBuilding simulation file : "+virtualHexFileName+"\n")
                   varguments+=["-s",vlibpath,"-asm",asmFileName,"-hex",virtualHexFileName,self.mainEditor.filename]
                   
                   if wx.Platform == '__WXMSW__':
                        p = subprocess.Popen(args=varguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
                   else :
                        p = subprocess.Popen(args=varguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False)

                   outputlines = p.stdout.readlines()
                   p.wait()
                
               self.asmParser = JalV2AsmParser()
               wholeCode = self.asmParser.parseAsmFile(asmFileName, [])
               
               if "virtual_delay" in anno_options :
                   self.buildEmu(virtualHexFileName,wholeCode)
               else :
                   self.buildEmu(self.hexFileName)
               
               self.langParser = JalV2AsmParser()
               
               # set langParser to debugView
               self.debugView.langParser = self.langParser
               
               code = self.langParser.parseAsmFile(asmFileName, noDebugList,debugList)
               self.loadDebugList(self.emu.instructionList,self.emu.lastAddress,code,wholeCode)
               self.varTypeDict = JalV2AsmParser.buildVarTypeDict(wholeCode)
               self.debugView.varTypeDict = self.varTypeDict
               
               #build in / out
               self.buildInOut(parseRes["inputs"],parseRes["outputs"])
               self.devices = parseRes["devices"]
              
               self.buildDevices(self.devices)
               self.top.toolbar.EnableTool(Context.TOOL_RUN,True)
               self.top.GetMenuBar().Enable(124,True)
               self.top.toolbar.EnableTool(Context.TOOL_RUN_UNIT_TEST,True)
               
           self.listUnitTest.DeleteAllItems()           
           self.markWarning(outputlines) # need to be done after loading jalFileName
           
           # to avoid some redraw coloring problems...
           self.mainEditor.Colourise(0,-1)
           self.browserEditor.Colourise(0,-1)
        
       self.top.SetCursor(STANDARD_CURSOR)
           
    
    
    def buildVirtualFileName(self,filename):
        path = os.path.dirname(filename)
        file = os.path.basename(filename)
        return path+os.sep+"~"+file
    
    def programMemCallBack(self,data,adr,lastAddress,instructionList):
        # any nedd to update asm debug list ?
        if adr<= lastAddress:
           self.asmParser = JalV2AsmParser()
           asmFileName = self.mainEditor.filename.replace(".jal",".asm")
           wholeCode = self.asmParser.parseAsmFile(asmFileName, [])
           self.loadDebugList(instructionList,lastAddress,None,wholeCode)            
    
    def buildEmu(self,hexFileName,wholeCode=None):
        adrDelay = None
        if wholeCode != None :
            jalCode = [""]*1024*128
            adrDelay = {}
            # build an array with address as index and code as content
            for i in range (0, len (wholeCode)) :
                adr = str(wholeCode[i].address).strip()
                if adr != "" :
                    if jalCode[int(adr)] != "":
                        jalCode[int(adr)] += str("-"+wholeCode[i].line)
                    else :
                        jalCode[int(adr)] = str(wholeCode[i].line)
            
            for i in range (0, len (jalCode)) :
                line = jalCode[i].replace("--",";")
                line = line.split(";")[0]
                line = line.upper().strip()
                if "DELAY_" in line and "PROCEDURE" not in line.upper():
                    line = line[line.index("DELAY_"):]
                    # print line
                    factor =1
                    if "MS" in line :
                        factor = 0.001
                    elif "US" in line :
                        factor = 0.000001
                    
                    time=0
                    nbr = 1
                    partNbr = line.split("(")
                    if len(partNbr) > 1:
                        nbr = partNbr[1]
                        try :
                            nbr = int(nbr.replace(")","").strip())
                        except : nbr = 1
                    time = line[6:]
                    time = re.split("[MSU]+",time)[0]
                    delay = int(time) * nbr * factor
                    adrDelay[i]= delay        
                    # print " adrDelay[i] %d " % i + " = %d " % delay
        
        self.emu = PicEngine.newInstance( self.picName , hexFileName, self.programMemCallBack, adrDelay)
        self.debugView.emu = self.emu
        
        mon = RegisterUpdater(self.debugView.watchedReg)
        devTarget =  DeviceTargetStateMonitor(self) # use to update device state from emu.state (ie led.. lcd...)
        devSource =  DeviceSourceStateMonitor(self) # used to update emu.state from device state (ie buttons)
        
        #profiler = ProfilerPulgin(self)
        #self.plugins = [profiler]     
        #self.emu.monitors = [profiler]     
        
        self.emu.state.globalWriteMonitors = [mon,devTarget]  
        self.emu.state.globalReadMonitors = [devSource] 
    
    def buildDevices(self,devices):
        if devices != None :
            nodeCounter = 0
            dc =wx.ClientDC ( self.drawWindow )
            self.drawWindow.diagram.Clear(dc)
            self.drawWindow.diagram.RemoveAllShapes()
           
            for i in range(0,1024*128):
                self.nodesForAddress[i] = None
                self.devicesForAddressRead[i] = None
                self.devicesForAddressWrite[i] = None
                
            for device in devices :
                parts = device.split(" ")
                deviceFullName = parts[1]
                deviceModule = deviceFullName.split(".")[0]
                deviceClass = deviceFullName.split(".")[1]
                deviceArgs = parts[2:]
                print sys.path
                exec("from %s import %s" % (deviceModule,deviceClass))
                
                deviceInstance = eval("%s()" % deviceClass)
                deviceInstance.NodeNr = [0] * (len(deviceArgs)+1)
                
                cptDeviceInstanceNodes = 1 # JALsPy defined that pin start at 1
                for arg in deviceArgs:
                    # transfer arg to device instance
                   
                    if "=" in arg :
                        parts = arg.split("=")
                        cmd = "deviceInstance.%s = %s" % (parts[0],parts[1])
                        exec(cmd)
                        
                    elif arg.startswith("pin_") :
                        pin = arg.upper()
                        #convert pin_a0 -> 5 bit 1
                        port = ord(pin[4])-60 
                        bit = pow(2,(ord(pin[5])-48))
                        
                        # some JALsPy needs...
                        JALsPy_globals.V_Node.append(1)
                        JALsPy_globals.G_Node.append(1)
                        JALsPy_globals.C_Node.append(1)
                        JALsPy_globals.T_Node.append(1)
                        deviceInstance.NodeNr[cptDeviceInstanceNodes] = nodeCounter
                        
                        # build a static map of (node - address_bit) for an address
                        # useful to update the NodeList (JALsPy_globals.V_Node) on which the device relies
                        # to know their states
                        nodesAndBits = self.nodesForAddress[port]
                        if (nodesAndBits == None) :
                            nodesAndBits = []
                        nodesAndBits.append((nodeCounter,bit)) # (6,128) -> node 0 is on portb bit 7 
                        self.nodesForAddress[port] = nodesAndBits   # [addr] = [(nodex,addr_bit),(nodey,addr_bit),...]
                        
                        # build a static map to retrieves all devices for an address
                        # useful to know wich devices need to be updated when a register changes
                        # comp needs update only if pic_pin  is output
                        #if self.emu.state.isOutput(port,bit): 
                        devicesForAddr = self.devicesForAddressWrite[port]
                        if (devicesForAddr == None) :
                            devicesForAddr = set()
                        devicesForAddr.add(deviceInstance)
                        self.devicesForAddressWrite[port] = devicesForAddr
                        print "device "+str(deviceInstance.__class__)+" binded to "+arg+" as target, node="+str(nodeCounter)
                        
                        #else :
                            #inputs
                        devicesForAddr = self.devicesForAddressRead[port]
                        if (devicesForAddr == None) :
                            devicesForAddr = set()
                        devicesForAddr.add(deviceInstance)
                        self.devicesForAddressRead[port] = devicesForAddr
                        print "device "+str(deviceInstance.__class__)+" binded to "+arg+" as source, node="+str(nodeCounter)
                        #end
                        
                        
                        cptDeviceInstanceNodes+=1
                        nodeCounter += 1
                        
                    elif arg.upper() == "LOW" or arg.upper() == "OFF" or arg.upper() == "FALSE":
                         print "device "+str(deviceInstance.__class__)+" connected to low, node="+str(nodeCounter)

                         deviceInstance.NodeNr[cptDeviceInstanceNodes] = nodeCounter
                         JALsPy_globals.V_Node.append(1)
                         JALsPy_globals.G_Node.append(1)
                         JALsPy_globals.C_Node.append(1)
                         JALsPy_globals.T_Node.append(1)
                         
                         JALsPy_globals.V_Node[nodeCounter] = 0 # 0 Volt
                         cptDeviceInstanceNodes+=1
                         nodeCounter += 1
                        
                        
                    elif arg.upper() == "HIGH" or arg.upper() == "ON" or arg.upper() == "TRUE":
                         print "device "+str(deviceInstance.__class__)+" connected to high, node="+str(nodeCounter)

                         deviceInstance.NodeNr[cptDeviceInstanceNodes] = nodeCounter
                         JALsPy_globals.V_Node.append(1)
                         JALsPy_globals.G_Node.append(1)
                         JALsPy_globals.C_Node.append(1)
                         JALsPy_globals.T_Node.append(1)
                         
                         JALsPy_globals.V_Node[nodeCounter] = 5 # 5 Volt
                         cptDeviceInstanceNodes+=1
                         nodeCounter += 1
                    
                deviceInstance.init()
                shape = deviceInstance.shape
                shape.SetX(deviceInstance.x)
                shape.SetY(deviceInstance.y)
                self.drawWindow.diagram.AddShape(shape)
                shape.Show(True)
                self.drawWindow.diagram.Redraw(dc)

                
            
        
    def buildInOut(self,inputs,outputs):
        self.inOutPanel.DestroyChildren()
        li = len(inputs)
        lo = len(outputs)
        max = li
        if lo>li :
            max = lo
        for i in range(0,max):
            if i< li:
                input = inputs[i]
                    
                if hasattr(input, "callbackRead"):
                    input.callbackRead = self.callbackRead
                if hasattr(input, "callbackWrite"):
                    input.callbackWrite = self.callbackWrite
                if hasattr(input, "callbackWriteAdc"):
                    input.callbackWriteAdc = self.callbackWriteAdc
                 
                but = input.CreateUI(self.inOutPanel,self.inOutSizer )

                # af need to find a cleaner way of doing this
                if hasattr(input, "hasData"):
                     self.emu.state.uartProvider = input
                
            else:
                self.inOutSizer.Add(wx.StaticText(self.inOutPanel,-1,""))
            if i< lo:
                output = outputs[i]
                comp = None
                                        
                varAdrMapping = None
                address = None
                						  
                if hasattr(self, "langParser"):
                        varAdrMapping = self.langParser.varAdrMapping
                        if hasattr(output, "address"):
                            output.address = Format.toNumber(str(output.address),varAdrMapping)

                output.CreateUI(self.inOutPanel, self.inOutSizer )
                comp = output
                    
                if (output.type=="uartReceiver"):
                    self.emu.state.uartReceiver = output
                
                if comp != None and hasattr(comp, "address"):                           
                     self.emu.state.appendMonitor( comp )
            else:
                self.inOutSizer.Add(wx.StaticText(self.inOutPanel,-1,""))
        
        #hack due to redraw problems on windows   
        self.bottomSplitter.SetSashPosition(self.bottomSplitter.GetSashPosition()+1,True) 
        self.bottomSplitter.SetSashPosition(self.bottomSplitter.GetSashPosition()-1,True) 

    #
    # Used by debug components to read a register
    #
    def callbackRead(self,port):
        return self.emu.state.absreg(port)
    #
    # Used by debug components to write a register
    #
    def callbackWrite(self,port,value):
        self.emu.state.abswrite(port,value)
        

    #
    # Used by debug components to write the ADC register for the specified analog channel
    #
    def callbackWriteAdc(self,pinNumber,value):
        # print "UPDATE ADC FROM UI channel: %d" % int( pinNumber ) + " to value %d" % value        
        self.emu.state.adc[int(pinNumber)] = value
    
    
    def reset(self):
        if self.running:
            self.stop() # reset will be call at the and of callback
            self.running = False
            self._reset()
        else:
            self._reset()
            
    def close(self,event): 
        app = Context.top
        Context.APP_SIZE_X = app.GetSize()[0]
        Context.APP_SIZE_Y = app.GetSize()[1]
        Context.APP_POS_X = app.GetPosition()[0]
        Context.APP_POS_Y = app.GetPosition()[1]
        Context.FONTSIZE += self.mainEditor.GetZoom()
        Context.BROWSER_SASH_POSITION = self.browserSplitter.GetSashPosition(0)
        Context.save()
                
        if self.running:
            self.needClose = True
            self.stop() # reset will be call at the and of callback
            time.sleep(1)
            sys.exit(0)
            event.Skip()
        else:
            sys.exit(0)
            event.Skip()
      
    
           
    def markWarning(self,outputlines):
        for lg in outputlines:
            if ".jal" in lg:
               
                try :
                    parts = lg.split(":") 
                    if self.mainEditor.filename == parts[0]+":"+parts[1]:
                        try :
                            if " warning:" in lg:   
                                self.mainEditor.markLineWarning(int(parts[2])-1) # error is 1 based
                        except : pass
                    elif  self.browserEditor.filename == parts[0]+":"+parts[1]:
                        try :
                            if " warning:" in lg:
                                self.browserEditor.markLineWarning(int(parts[2])-1) # error is 1 based
                        except : pass
                except : pass
                
    def OnErrorListDCLICK(self,event):
        filename = self.listResult.GetItem(self.listResult.GetFirstSelected(),1)
        filename = filename.GetText().strip()

        if ( filename == self.mainEditor.filename ) :
           self.tab.SetSelection( Context.TAB_EDIT )
        else:
           self.openEditor(Context.TAB_BROWSER, filename)
           self.tab.SetSelection( Context.TAB_BROWSER )
           
        self.OnErrorList(event)
            
    def OnErrorList(self,event):
        lg = self.listResult.GetItem(self.listResult.GetFirstSelected(),0)
        lg = lg.GetText().strip()
        filename = self.listResult.GetItem(self.listResult.GetFirstSelected(),1)
        filename = filename.GetText().strip()
        if (lg != ""):
            if (self.mainEditor.filename == filename):
                self.tab.SetSelection(Context.TAB_EDIT)
                self.mainEditor.GotoLine(int(lg)-1)
                self.mainEditor.SetCurrentPos(self.mainEditor.GetLineEndPosition(int(lg)-1))
                self.mainEditor.SetFocus()
            
            elif self.browserEditor.filename == filename:
                self.tab.SetSelection(Context.TAB_BROWSER)
                self.browserEditor.GotoLine(int(lg)-1)
                self.browserEditor.SetCurrentPos(self.browserEditor.GetLineEndPosition(int(lg)-1))
                self.browserEditor.SetFocus()
    

    def _reset(self):
        self.top.SetCursor(HOURGLASS_CURSOR)
        
        #
        # Realy dirty need to be cleaned !
        #
        self.clearDebugListSelectedLine()
        self.buildDevices(self.devices)
        self.debugView.Clear()
        
        for plugin in self.plugins:
            plugin.reset()        
            
        uartProvider = None
        uartReceiver = None
        # get a thread engine
        if self.emu != None:
            if hasattr(self.emu.state, "uartProvider"):
                uartProvider = self.emu.state.uartProvider
            if hasattr(self.emu.state, "uartReceiver"):
                uartReceiver = self.emu.state.uartReceiver
            
            if hasattr(self.emu.state, "monitors"):
                monitors = self.emu.state.monitors
                for mon in monitors:
                    mon.reset()
                    
            
            hexFileName = self.emu.hexfilename

            parseRes = AnnotationParser.parse(self.mainEditor.GetText())
            self.buildEmu(hexFileName)

            self.emu.state.monitors = monitors
            
            if uartProvider != None :
                self.emu.state.uartProvider = uartProvider
            if uartReceiver != None :
                self.emu.state.uartReceiver = uartReceiver
            
            # Update asm list as it may have been update by program flash change
            self.asmParser = JalV2AsmParser()
            asmFileName = self.mainEditor.filename.replace(".jal",".asm")
            parse_an = parseRes["options"]
            
            if "virtual_delay" in parse_an :
                asmFileName = self.buildVirtualFileName(asmFileName)
           
            if os.path.exists(asmFileName):
                wholeCode = self.asmParser.parseAsmFile(asmFileName, [])
                self.loadDebugList(self.emu.instructionList, self.emu.lastAddress, None, wholeCode)
                
            
            noDebugList = parseRes["noDebug"] 
            debugList =parseRes["debug"]  
           
            if parseRes["regfilter"] != "":
               self.debugView.regFilter.SetLabel(parseRes["regfilter"])
            if parseRes["varfilter"] != "":
               self.debugView.varFilter.SetLabel(parseRes["varfilter"])
               
            self.hexFileName = self.mainEditor.filename.replace(".jal",".hex")
            virtualHexFileName = self.buildVirtualFileName(self.hexFileName)
            self.asmParser = JalV2AsmParser()
            wholeCode = self.asmParser.parseAsmFile(asmFileName, [])
            if "virtual_delay" in parse_an :
                self.buildEmu(virtualHexFileName,wholeCode)
            else :
                self.buildEmu(hexFileName)
           
            self.langParser = JalV2AsmParser()
            
            # set langParser to debugView
            self.debugView.langParser = self.langParser
            
            code = self.langParser.parseAsmFile(asmFileName, noDebugList,debugList)
            self.loadDebugList(self.emu.instructionList,self.emu.lastAddress,code,wholeCode)
            self.varTypeDict = JalV2AsmParser.buildVarTypeDict(wholeCode)
            self.debugView.varTypeDict = self.varTypeDict
           
            wx.Yield()
            self.buildInOut(parseRes["inputs"],parseRes["outputs"])
            
            #build in / out
            
            self.devices = parseRes["devices"]
          
            self.buildDevices(self.devices)
            self.top.toolbar.EnableTool(Context.TOOL_RUN,True)
            self.top.GetMenuBar().Enable(124,True)
            self.top.toolbar.EnableTool(Context.TOOL_RUN_UNIT_TEST,True)
        
            self.updateBreakPoints()
        
            self.statusBar.SetStatusText("Reseted")
        self.top.SetCursor(STANDARD_CURSOR)        
    #----------------------------------------------------------------
    # Editor
    #

    # Update editor
    # content : an array of lines
    def updateEditor(self,whichEditor,lines):
        if (whichEditor == 0) or (whichEditor == 1): 
            editor = self.mainEditor
        else :
            editor = self.browserEditor
        content =""
        for line in lines:
            content += line
        editor.SetText(content)

    def getEditor(self,whichEditor):
        if (whichEditor == 2) : 
            editor = self.browserEditor
        else :
            editor = self.mainEditor
        return editor

    # Which editor is the curent Tab
    def saveEditor(self,whichEditor):
        self.top.SetCursor(HOURGLASS_CURSOR)
        editor = self.getEditor(whichEditor)
        filename =  FileUtil.saveEditor(editor.filename,editor)
        if filename!="":
            editor.filename = filename
        self.top.SetCursor(STANDARD_CURSOR)
            
        return filename
    
    def saveEditorAs(self,whichEditor):
        self.top.SetCursor(HOURGLASS_CURSOR)
        editor = self.getEditor(whichEditor)
        filename =  FileUtil.saveEditor("",editor)
        if filename!="":
            editor.filename = filename
        self.top.SetCursor(STANDARD_CURSOR)
        return filename
    
    def openEditor(self,whichEditor,filename="",newProject=False):
        editor = self.getEditor(whichEditor)
        if filename=="":
            filename = FileUtil.open()
        if filename != "":
            if newProject:
                self.newProject()  
            editor.filename = filename
            #editor.SetText(FileUtil.getContentAsText(filename))
            editor.LoadFile(filename)
            editor.ConvertEOLs(STC_EOL_CRLF)
            self.tab.SetPageText(whichEditor,filename)
            print "SET TAB TEXT %d to " % whichEditor + filename
                    
        if (whichEditor!=Context.TAB_BROWSER):
            self.updateOutLineTree()
            self.browserView.updateTree(self.mainEditor.filename, self.mainEditor.GetText())
            
        return filename
    
    
    def updateDeepSearchTree(self,match,lib):
        self.deepSearchTree.DeleteAllItems()
        if match != "" :
            allpathes = FileUtil.expand_paths( os.path.dirname(self.mainEditor.filename)+";"+Context.libpath )
            match = match.strip()
            #libs = EditorUtil.findAllLibsWithPath(allpathes)
            if self.mainEditor.filename != "" :
                files =[self.mainEditor.filename]
            else:
                files = []
            if lib :
                files += EditorUtil.findAllLibsWithPath(allpathes)
            else :
                files += list(EditorUtil.findAllIncludesWithPath(self.mainEditor.GetText(),allpathes))
            
            root = self.deepSearchTree.AddRoot('Root')
            for filename in files:
                fileRoot = None
                file = open (filename)
                num = 0
                for lg in file:
                    
                    #include comment ?
                    if not self.searchInComment.IsChecked() :
                        lg = lg.replace("--",";")
                        lg = lg.split(";")[0]
                    
                    num +=1
                    found = True
                    for m in match.split(" "):
                        if m.upper() not in lg.upper() :
                            found = False
                            break
                    
                    if found :
                        if fileRoot == None :
                            fileRoot = self.deepSearchTree.AppendItem(root,  filename)
                            self.deepSearchTree.SetItemBold(fileRoot,True)
                        self.deepSearchTree.AppendItem(fileRoot,  str(num)+":"+lg.strip())
                    if fileRoot != None :
                        self.deepSearchTree.Expand(fileRoot)
                        
                file.close()
    
    def OnDeepSearchTreeSelChanged(self, event):
        try :
            item =  event.GetItem()
            itemText = self.deepSearchTree.GetItemText(item)
            parentItem = self.deepSearchTree.GetItemParent(item)
            parentText =  self.deepSearchTree.GetItemText(parentItem)
            editor = None
            if self.mainEditor.filename == parentText :
                editor = self.mainEditor
                self.tab.SetSelection(Context.TAB_EDIT)
            else :
                self.tab.SetSelection(Context.TAB_BROWSER)
                if not self.browserEditor.filename.endswith("*"):
                    editor = self.browserEditor
                    self.openEditor(2,filename=parentText)
            if editor != None :
                line = -1
                line = int(itemText.split(":")[0])-1
                if line >-1:
                    editor.GotoLine(line)
                    editor.SetSelectionStart(editor.GetLineEndPosition(line)- len(editor.GetLine(line))+2)
                    editor.SetSelectionEnd(editor.GetLineEndPosition(line))                
        except : pass
    
    #----------------------------------------------------------------
    # OutLine Tree
    #
    
    # Update the outline tree
    # lines : content of the main editor as an array of lines
    def updateOutLineTree(self,match=""):
        self.clearOutLineTree()
        root = self.outLineTree.AddRoot('Root')
        varRoot = self.outLineTree.AppendItem(root,  'Global')
        funcRoot = self.outLineTree.AppendItem(root, 'Functions')
        procRoot = self.outLineTree.AppendItem(root, 'Procedures')
        annotationRoot = self.outLineTree.AppendItem(root, 'Annotations')
        
        self.outLineTree.SetItemBold(funcRoot,True)
        self.outLineTree.SetItemBold(procRoot,True)
        self.outLineTree.SetItemBold(varRoot,True)
        self.outLineTree.SetItemBold(annotationRoot,True)
        
        self.outLineTree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnOutlineTreeSelChanged, id=1)
        lines = self.mainEditor.GetText().split("\n")
        (funcs,procs,vars) = JalV2Parser.parse(lines)

        
        
        for f in funcs:
            parentAdded = False
            if match == "" or match.upper() in f.upper():
                item = self.outLineTree.AppendItem(funcRoot, f)
                parentAdded = True
            for v in funcs[f]:
                if match == "" or match.upper() in v.name.upper():
                    if not parentAdded:
                        item = self.outLineTree.AppendItem(funcRoot, f)
                        parentAdded = True    
                    self.outLineTree.AppendItem(item, v.type+" "+v.name)
                    if match != "":
                        self.outLineTree.Expand(item)
        for p in procs:
            parentAdded = False
            if match == "" or match.upper() in p.upper():
                item = self.outLineTree.AppendItem(procRoot, p)
                parentAdded = True
            for v in procs[p]:
                if match == "" or match.upper() in v.name.upper():
                    if not parentAdded:
                        item = self.outLineTree.AppendItem(procRoot, p)
                        parentAdded = True    
                    self.outLineTree.AppendItem(item, v.type+" "+v.name)
                    if match != "":
                        self.outLineTree.Expand(item)
        for v in vars:
            if match == "" or match.upper() in v.name.upper():
                self.outLineTree.AppendItem(varRoot, v.type+" "+v.name)
                
        annotations = AnnotationParser.findAnnotations(self.mainEditor.GetText())
        for a in annotations:
            if match == "" or match.upper() in a.upper():
                self.outLineTree.AppendItem(annotationRoot, a)       

        self.outLineTree.Expand(funcRoot)
        self.outLineTree.Expand(procRoot)
        self.outLineTree.Expand(varRoot)
        self.outLineTree.Expand(annotationRoot)
    
    def clearOutLineTree(self):
        self.outLineTree.DeleteAllItems()

    def OnOutlineTreeSelChanged(self,event):
        try:
            item =  event.GetItem()
            itemText = self.outLineTree.GetItemText(item)        
            parentItem = self.outLineTree.GetItemParent(item)
            line = -1
            
            parentText =  self.outLineTree.GetItemText(parentItem)
            if "Functions" == parentText:
                line = EditorUtil.findLineForFunc(self.mainEditor.GetText(),itemText)
            elif "Procedures" == parentText:
                line = EditorUtil.findLineForProc(self.mainEditor.GetText(),itemText)
            elif "Global" == parentText:
                line = EditorUtil.findLineForVar(self.mainEditor.GetText(),itemText)
            elif "Annotations" == parentText:
                line = EditorUtil.findLineForAnnotation(self.mainEditor.GetText(),itemText)
            
            else:
                line = EditorUtil.findLineForVar(self.mainEditor.GetText(),itemText,parentText)       
            if line >-1:
                self.mainEditor.GotoLine(line)
                self.mainEditor.SetSelectionStart(self.mainEditor.GetLineEndPosition(line)- len(self.mainEditor.GetLine(line))+2)
                self.mainEditor.SetSelectionEnd(self.mainEditor.GetLineEndPosition(line))
        except : pass


    def OnDeepSearchIncludes(self,event):
        what = self.deepSearchText.GetValue() 
        self.updateDeepSearchTree(what,False)
    def OnDeepSearchLibs(self,event):
        what = self.deepSearchText.GetValue() 
        self.updateDeepSearchTree(what,True)

    def OnOutlineSearch(self,event):
        key = event.GetKeyCode()
        if key == 319 or key == 13:
            self.outLineTree.SetFocus()
        what = self.outLineSearch.GetValue() 
        self.updateOutLineTree(what)
    
    
    #-------------------------------------------------------------------------------
    # Next action
    # 
    def nextAsm(self):
        self.top.SetCursor(HOURGLASS_CURSOR)
        self.curCycles = self.emu.state.GetCycles()

        if (not self.running) and self.listAsm.GetItemCount()>0:
           if (self.threadEngine != None):
                self.threadEngine.stop()
           self.tab.SetSelection(Context.TAB_DEBUG) # goto debug tab
           adr = self.emu.runNext()
           inst = self.emu.getCurInst() 
           self.explainAsmText.SetLabel("")
           self.explainAsmText.AppendText( AsmDocHelp.getAsmDescriptionHelp(inst, self.emu.state))
           self.explainAsmText.AppendText( AsmDocHelp.getAsmBeforeExecutionHelp(inst, self.emu.state))
           self.callback(adr)
           self.explainAsmText.AppendText( AsmDocHelp.getAsmAfterExecutionHelp(inst, self.emu.state))
        self.top.SetCursor(STANDARD_CURSOR)
        newCycles = self.emu.state.GetCycles()
        self.statusBar.SetStatusText("Cycles %d" % newCycles + ", delta cycles %d" % ( newCycles - self.curCycles ) )  
    
    def nextLang(self):
        self.top.SetCursor(HOURGLASS_CURSOR)
        self.curCycles = self.emu.state.GetCycles()
        if (not self.running) and self.listAsm.GetItemCount()>0:
           if hasattr(self, "allLineAddresses"): # inactif si import hex
               addresses = dict( self.allLineAddresses )

               # include asm breakpoint(s)
               for bp in self.breakpoints:
                  addresses[bp] = True 
               #print "ADDRESSES incl BP"
               #print addresses
               self._runTo(addresses ,self.unitTestCallBack)
        self.top.SetCursor(STANDARD_CURSOR)
        newCycles = self.emu.state.GetCycles()
        self.statusBar.SetStatusText("Cycles %d" % newCycles + ", delta cycles %d" % ( newCycles - self.curCycles ) )  
        
    # not fully woking for now...    
    def nextStepOverLang(self):
        text =  self.listAsm.GetItem(self.emu.state.pc,Context.COL_COM).GetText()
        print text,
        if not JalV2Parser.mustStepOver(text):
            self.nextLang()
            return    
        
        self.top.SetCursor(HOURGLASS_CURSOR)
        if (not self.running) and self.listAsm.GetItemCount()>0:
            addresses =  [0]*1024*128
            for i in range (0,len( addresses )):
                addresses[i] = False
           
            for a in self.langParser.lineToAdr :
                if (a != None) and (int(a) > self.emu.state.pc) :
                    addresses[a] = True
                    break
            
            # include breakpoint
            for adr,hasBreakpoint in enumerate(self.breakpoints):
                if hasBreakpoint :
                      addresses[adr] = True 
            self._runTo(addresses,self.unitTestCallBack)
        self.top.SetCursor(STANDARD_CURSOR)
           
    def stop(self):
       
       if (self.threadEngine != None):
          self.threadEngine.stop()
          
          #while self.threadEngine.stopped == False : pass
       if ( self.emu != None ):   
       	self.statusBar.SetStatusText("Stopped, cycles: %d" % self.emu.state.GetCycles())  
       else:	
       	self.statusBar.SetStatusText("Stopped")  
 

    def run(self):
         if (not self.running) and self.listAsm.GetItemCount()>0:
            self._runTo(self.breakpoints)
            
    def runUnitTest(self):
        if (not self.running) and self.listAsm.GetItemCount()>0:
             if self.emu != None :
                 self.listUnitTest.DeleteAllItems()
                 lastAddressArray = {}
                 if self.picName.startswith( "18f" ):
                    #print "SET LAST ADDRESS TO %06X " % ( self.emu.lastAddress-2 )
                    lastAddressArray[self.emu.lastAddress-2] = True
                 else:
                    lastAddressArray[self.emu.lastAddress] = True
                    
                 
                 self._runTo(lastAddressArray,self.unitTestCallBack)
             
    
    def _runTo(self,to,unitTestCallBack=None):
       
       if self.emu != None :
           self.curCycles = self.emu.state.GetCycles()
       
           self.stop()
           self.running = True
           self.disableActionWidget()
           self.clearDebugListSelectedLine()
           self.tab.SetSelection(Context.TAB_DEBUG) # goto debug tab
           self.threadEngine = PicThreadEngine(self.emu,unitTestCallBack) 
           self.threadEngine.callback = self.callback
           self.threadEngine.runTillAddress = to
           #print "Starting thread"
           self.threadEngine.start() 
           self.statusBar.SetStatusText("Running")  
    
    def toggleBreakPointAtAdr(self,adr):
        if adr != None:
            # self.breakpoints[adr] = not self.breakpoints[adr]
            if self.breakpoints.has_key( adr ):
               del self.breakpoints[adr]
            else:
               self.breakpoints[adr] = True
               
            #if (self.breakpoints[adr]):
            if (self.breakpoints.has_key( adr )):
                mark ="X"
                self.listBreakpoint.InsertStringItem(0,str(adr))
            else:
                mark =""
                # TODO : remove breakpoint from list
                self._removeBreakPointFromList(str(adr))
                
            self.listAsm.SetStringItem(adr,Context.COL_BP,mark)
            if  hasattr(self, "langParser") and self.langParser.adrToLine[adr] != None :
                self.listLang.SetStringItem(self.langParser.adrToLine[adr],Context.COL_BP,mark)
                
                #if (self.breakpoints[adr]):
                if (self.breakpoints.has_key(adr)):
                    tmpText =  self.listLang.GetItem(self.langParser.adrToLine[adr],Context.COL_CODE).GetText()
                    self.listBreakpoint.SetStringItem(0,1,tmpText)
                
            if (self.threadEngine != None):
               self.threadEngine.runTillAddress = self.breakpoints  
               self.clearDebugListSelectedLine()  
    def updateBreakPoints(self):
        self.listBreakpoint.DeleteAllItems()
        for adr in range(0,self.listAsm.GetItemCount()) :
            #if (self.breakpoints[adr]):
            if (self.breakpoints.has_key(adr)):
                mark ="X"
                self.listBreakpoint.InsertStringItem(0,str(adr))
            else:
                mark =""
                # TODO : remove breakpoint from list
                self._removeBreakPointFromList(str(adr))
                
            self.listAsm.SetStringItem(adr,Context.COL_BP,mark)
            if  hasattr(self, "langParser") and self.langParser.adrToLine[adr] != None :
                self.listLang.SetStringItem(self.langParser.adrToLine[adr],Context.COL_BP,mark)
                
                #if (self.breakpoints[adr]):
                if (self.breakpoints.has_key(adr)):
                    tmpText =  self.listLang.GetItem(self.langParser.adrToLine[adr],Context.COL_CODE).GetText()
                    self.listBreakpoint.SetStringItem(0,1,tmpText)
    
    def _removeBreakPointFromList(self,adr):
        lineToRemove = []
        cpt = self.listBreakpoint.GetItemCount()
        for i in range (0,cpt):
            curAdr =  self.listBreakpoint.GetItem(i,0).GetText()
            if curAdr == adr :
                lineToRemove.append(i)
        for i in lineToRemove:
            self.listBreakpoint.DeleteItem(i)
            
            
        
        
    def OnBreakPointAsm(self,event):
        adr = self.listAsm.GetFirstSelected()
        self.toggleBreakPointAtAdr(adr)
        
    def OnBreakPointLang(self,event):
        adr = self.langParser.lineToAdr[self.listLang.GetFirstSelected()]
        self.toggleBreakPointAtAdr(adr)
        
    def OnListLangSelected(self,event):
        self.currentItemDebug = event.m_itemIndex 
        # sync list asm
        item = self.listLang.GetItem(self.currentItemDebug,Context.COL_ADR)
        adr =  item.GetText().strip()
        if (adr != ""):
            self.listAsm.Select(int(adr,16), True)
            self.listAsm.EnsureVisible(int(adr,16))
    #-------------------------------------------------------------------------------
    # Next action
    # 
    def callback(self,adr):
        evtCallBack = self.UpdateCallbackEvent(adr = adr)
        wx.PostEvent(Context.frame, evtCallBack)


        
    def unitTestCallBack(self,address):
        #print "callback for address : "+str(address) 
        label =""
        res= ""
        status = "ERROR"
        item = 0 # insert error on top
        color = "red"
        if address >= len(self.langParser.adrToLine):
            res =  "Address is out of bound [0..8191] : "+str(address)
            status = "ERROR"
            self.listUnitTest.InsertStringItem(item,label)
            self.listUnitTest.SetStringItem(item,1,status)
            self.listUnitTest.SetStringItem(item,2,res)
            self.listUnitTest.SetItemTextColour(item,color)
        else :    
            line = self.langParser.adrToLine[address]
            if line != None:
                code =  self.listLang.GetItem(line,Context.COL_CODE).GetText()
                assertTag = AssertUtil.GetAssertTag( code )                

                if assertTag != None:                	 
                    res = AssertUtil.parse(code,assertTag)
                    var = res["var"].lower()
                    label = res["label"]
                    ref = res["ref"]
                    if (self.langParser.varAdrMapping.has_key("v_"+var)):
                        varAddr = self.langParser.varAdrMapping["v_"+var]
                        # print self.varTypeDict
                        
                        if self.varTypeDict.has_key( var ):
                            varType = type = self.varTypeDict[var]
                        else:
                            varType = "Unknown type: "
                        
                        val = self.emu.varValue(varAddr,varType)  
                        
                        [assertRes, cmpStr ] = AssertUtil.Assert( assertTag, val, ref )
                        
                        res= varType+ " " + var + " (@"+str(varAddr)+") = 0x%X " % val + cmpStr + " expected : 0x%X" % ref
                        
                        if ( assertRes ) :
                            status = "PASS"
                            color ="#008000"
                            item = self.listUnitTest.GetItemCount()
                        else :
                            status = "FAIL"
                            
                    else :
                        status = "ERROR"
                        res = "Test can't be run, var "+var+" can't be identified (address not found in asm file)"

                    self.listUnitTest.InsertStringItem(item,label)
                    self.listUnitTest.SetStringItem(item,1,status)
                    self.listUnitTest.SetStringItem(item,2,res)
                    self.listUnitTest.SetItemTextColour(item,color)
                    
   
    def enableActionWidget(self):
        self.bNextLang.Enable()
        self.bNextAsm.Enable()
        self.top.toolbar.EnableTool(Context.TOOL_RUN,True)
        self.top.GetMenuBar().Enable(124,True) # Run Menu
        
        self.top.toolbar.EnableTool(Context.TOOL_RUN_UNIT_TEST,True)
        
        self.top.toolbar.EnableTool(Context.TOOL_COMPILE,True)
        
        self.top.toolbar.EnableTool(Context.TOOL_OPEN,True)
        self.top.toolbar.EnableTool(Context.TOOL_NEW,True)
        self.top.GetMenuBar().Enable(100,True)
        self.top.GetMenuBar().Enable(101,True)
        self.top.GetMenuBar().Enable(103,True)
        


    def disableActionWidget(self):
        if platform.machine()=='i386':
            self.bNextLang.Disable() # TODO : seems not to work well on linux ???
        
        self.bNextAsm.Disable()
        self.top.toolbar.EnableTool(Context.TOOL_RUN,False)
        self.top.GetMenuBar().Enable(124,False) # Run Menu

        self.top.toolbar.EnableTool(Context.TOOL_RUN_UNIT_TEST,False)
        self.top.toolbar.EnableTool(Context.TOOL_COMPILE,False)
        
        self.top.toolbar.EnableTool(Context.TOOL_OPEN,False)
        self.top.toolbar.EnableTool(Context.TOOL_NEW,False)
        self.top.GetMenuBar().Enable(100,False)
        self.top.GetMenuBar().Enable(101,False)
        self.top.GetMenuBar().Enable(103,False)

        
        
    def clearDebugListSelectedLine(self):
       if hasattr(self, "listLang") : 
           item = self.listLang.GetFirstSelected()
           if item != -1:     
               self.listLang.Select(item,False)  
           while item != -1:
                item = self.listLang.GetNextSelected(item)
                self.listLang.Select(item,False)
           
       item = self.listAsm.GetFirstSelected()
       if item != -1:         
           self.listAsm.Select(item,False)
       
    def gotoTopDebugList(self):
       if hasattr(self, "listLang") :
           self.listLang.Select(0,True)
           self.listLang.EnsureVisible(0)
      
       self.listAsm.Select(0,True)
       self.listAsm.EnsureVisible(0)
       
    #----------------------------------------------------------------
    # Lists (ASM AND LANG)
    #
    def updateDebugListPosition(self,adr):
        self.clearDebugListSelectedLine()
        self.listAsm.Select(adr, True)
        self.listAsm.EnsureVisible(long(adr))

        if ( self.emu != None ) :        
        	newCycles = self.emu.state.GetCycles()
        	self.statusBar.SetStatusText("Cycles %d" % newCycles + ", delta cycles %d" % ( newCycles - self.curCycles ) )  
        
        if hasattr(self, "langParser"):
            langLine = self.langParser.adrToLine[adr]
            
            if (langLine != None):
                self.listLang.Select(langLine, True)
                nbLines = self.listLang.GetItemCount() 
                for i in range(langLine,nbLines):
                    nextadr =  self.listLang.GetItem(i,Context.COL_ADR).GetText()
                    try :
                        nextadr = int(nextadr,16)
                        if adr == nextadr:
                            self.listLang.Select(i, True)
                        else:
                            break
                    except :
                        break
                self.listLang.EnsureVisible(long(langLine))
    
    def loadDebugList(self,instructionList,lastAddress,code,wholeCode):
        self.listAsm.DeleteAllItems()
        if code != None:
            self.listLang.DeleteAllItems()
        
        # fill asm list
        for i in range(0,lastAddress+1):
            inst = instructionList[i]
            self.listAsm.InsertStringItem(i, "")
            self.listAsm.SetStringItem(i,Context.COL_ADR,  "%06X" % inst.adresse )
            self.listAsm.SetStringItem(i,Context.COL_CODE, Format.formatInstructionWithoutAddress(inst, 0, True).strip())
            #print str(inst.adresse)+" "+Format.formatInstructionWithoutAddress(inst, 0, False).strip()
            
    
        # decorate with jal comment
        for i in range (0,len(wholeCode)):
           if (wholeCode[i] != None):
               if (self.asmParser.lineToAdr[i] != None):
                  
                      text = wholeCode[i].line
                      tmpText =  self.listAsm.GetItem(self.asmParser.lineToAdr[i],Context.COL_COM).GetText()
                      if (tmpText.strip() != ''):
                          try :
                              text = unicode(tmpText+" / "+wholeCode[i].line)
                          except : 
                              print "Warning : Exception occurs in UIManager.loadDebugList on text :"
                              print tmpText,
                              print " / ",
                              print wholeCode[i].line
                      try :        
                          self.listAsm.SetStringItem(self.asmParser.lineToAdr[i],Context.COL_COM,text.replace("\t","    ")) 
                      except :
                          first_error = False
                          # something got wrong...
                          print "======================================================="
                          print "Error in UIManager.loadDebugList(...)"
                          print i        
                          print text
                          print "Unreachable adress : "+str(self.asmParser.lineToAdr[i])
                          print "======================================================="
                          
        if code != None :      
            # fill lang list

            self.allLineAddresses =  {}

            for i in range (0,len(code)):
               if (code[i] != None):
                  #print "PL : " code[i].line
                  self.listLang.InsertStringItem(i,"") # breakpoint
                  if code[i].address != " ":
                      # print ":" + code[i].address + ":"
                      self.listLang.SetStringItem(i,Context.COL_ADR, "%06X" % code[i].address)
                  else:
                      self.listLang.SetStringItem(i,Context.COL_ADR, "")
                      
                  self.listLang.SetStringItem(i,Context.COL_CODE, code[i].line.replace("\t","    "))
                  
                  if code[i].address != " ":
                      self.allLineAddresses[code[i].address] = True
                     
                  curLine = self.listLang.GetItem(i,Context.COL_CODE).GetText()
                  upCurLine = curLine.upper()
                  if (curLine.startswith('--')):
                      self.listLang.SetItemTextColour(i,'#55CC55')
                  elif ('PROCEDURE' in upCurLine)  or ('FUNCTION' in upCurLine) or ('LOOP' in upCurLine) or ('IF ' in upCurLine) or ('ELSE' in upCurLine) or ('END ' in upCurLine):
                      font = self.listLang.GetItemFont(i)
                      font.SetWeight(wx.BOLD)
                      font.SetPointSize(8)
                      self.listLang.SetItemFont(i,font)
                      # set asm list boldness
                      try :
                          self.listAsm.SetItemFont(self.langParser.lineToAdr[i],font)
                      except : pass

    def OnRemoveAllBreakpoints(self,event):
        self.removeAllBreakpoints()
        
    def removeAllBreakpoints(self):
        # clear bp
        #for i in range(0,len( self.breakpoints ) ):
        #    self.breakpoints[i] = False  
        #for i in range(0,len( self.breakpoints ) ):
        self.breakpoints = {}

        # remove marks
        nb = self.listLang.GetItemCount()
        for i in range (0,nb):
            self.listLang.SetStringItem(i,Context.COL_BP,"")
        nb = self.listAsm.GetItemCount()
        for i in range (0,nb):
            self.listAsm.SetStringItem(i,Context.COL_BP,"")
        
        #clear list
        self.listBreakpoint.DeleteAllItems()
    
    
    def OnlistBreakPointSelected(self,event):
        currentItem = event.m_itemIndex
        adr =  self.listBreakpoint.GetItem(currentItem,0).GetText()
        line = None
        if hasattr(self, "langParser") : 
            line = self.langParser.adrToLine[int(adr)]
        self.clearDebugListSelectedLine()
       
        if  line != None :
            self.listLang.Select(line, True)
            self.listLang.EnsureVisible(line)
        else:
            self.listAsm.Select(int(adr), True)
            self.listAsm.EnsureVisible(int(adr))
  
    def findReplace(self):
        pageNumber = self.tab.GetSelection()
        dlg = None
        if pageNumber == Context.TAB_EDIT :
            dlg = FindDialog(self.mainEditor, -1, "Find/Replace",style = wx.DEFAULT_DIALOG_STYLE)
        if pageNumber == Context.TAB_BROWSER :
            dlg = FindDialog(self.browserEditor, -1, "Find/Replace",style = wx.DEFAULT_DIALOG_STYLE)
        if dlg != None:    
            dlg.CenterOnScreen()
            dlg.Show()
    def findPinMapping(self):
            res =""
            allLines = self.mainEditor.GetText().split("\n")
            res+="-- ---------------------------------\n"  
            res+="-- Pin and Port Direction\n"  
            res+="-- ---------------------------------\n"  
            i=0
            for line in allLines :
                i += 1
                lc = line.upper()
                lc = lc.replace("--",";")
                lc = lc.split(";")[0]
                if "_DIRECTION" in lc :
                    res+= str(i)+": "+line+"\n"

            res+="-- ---------------------------------\n"  
            res+="-- Pin and Port Alias\n"  
            res+="-- ---------------------------------\n"  
            i=0
            for line in allLines :
                i += 1
                lc = line.upper()
                lc = lc.replace("--",";")
                lc = lc.split(";")[0]
               
                if " IS " in lc :
                    res+= str(i)+": "+line+"\n"
                
            res+="-- ---------------------------------\n"  
            res+="-- Pin and Port usage without alias\n"  
            res+="-- ---------------------------------\n"  
            i = 0
            for line in allLines :
                i += 1
                lc = line.strip().upper()
                lc = lc.replace("--",";")
                lc = lc.split(";")[0]
               
                if " IS " in lc :
                    pass
                elif "_DIRECTION" in lc :
                    pass
                elif "PIN_" in lc :
                    res+=str(i)+": "+line+"\n"
                elif re.search("[\t\)\n ]?PORT[ABCDE]\W",lc) :
                    res+=str(i)+": "+line+"\n"
          
            self.helpText.SetText(res)

  
    def importHex(self,filename=""):
        if filename=="":
            filename = FileUtil.open("*.hex")
        if filename != "":
            self.newProject()
            self.buildEmu(filename)
            self.top.toolbar.EnableTool(Context.TOOL_RUN,True)
            self.top.GetMenuBar().Enable(124,True)
            self.top.toolbar.EnableTool(Context.TOOL_RUN_UNIT_TEST,True)
            self.loadDebugList(self.emu.instructionList,self.emu.lastAddress,None,[])
            self.tab.SetSelection(Context.TAB_DEBUG) # goto debug tab

        annotationsFilename = filename.replace(".hex",".txt")
        if os.path.exists(annotationsFilename):
            self.openEditor(Context.TAB_EDIT, annotationsFilename, False)
            parseRes = AnnotationParser.parse(self.mainEditor.GetText())
            self.buildInOut(parseRes["inputs"],parseRes["outputs"])

    def showPreferences(self):
        dlg = PreferencesDialog(self.mainEditor, -1, "Preferences",style = wx.DEFAULT_DIALOG_STYLE)
        dlg.CenterOnScreen()
        dlg.ShowModal()
        dlg.Destroy()
        
    #----------------------------------------------------------------
    # Log a message
    #
    def log(self,message):
        print message

    #
    # jallib style guide validator
    #
    def JSGValidate(self):
        validator = JSGValidator()
        self.compileLog.Clear()
        self.listResult.DeleteAllItems()

        validator.Validate( [self.mainEditor.filename] )
        
        hasErrors = self.HandleCompilerErrorResults(validator.outputlines)
        self.markWarning(validator.outputlines)

        if (hasErrors):
            self.tab.SetSelection(Context.TAB_EDIT) # goto edit tab
            self.top.GetStatusBar().SetStatusText("Validation status : Errors")
            self.compileTab.SetSelection(Context.COMPILE_ERROR_TAB) 
        else:
            #update list, use the parsers...
            self.compileTab.SetSelection(Context.COMPILE_RESULT_TAB)
            self.top.GetStatusBar().SetStatusText("Validation status : Ok")                
        
    #
    # export a file and its dependencies in a single zip file
    #
    def exportBundle(self):
        mainfile = self.getEditor(Context.TAB_EDIT).filename
        if mainfile =="" :
            wx.MessageBox("Unable to get current file name")
            return
       
        defaultname = os.path.basename(mainfile).split(".jal")[0]
        allincludes = EditorUtil.findAllIncludedFiles(self.mainEditor.GetText(),os.path.dirname(mainfile)+";"+Context.libpath)
       
        dlg = wx.FileDialog(Context.top,"Choose a file", Context.sourcepath, defaultname+".zip", "*.zip", wx.SAVE)
        if dlg.ShowModal() == wx.ID_OK:
            zipfilename = dlg.GetPath()
            dlg.Destroy()
            if wx.Platform == '__WXMSW__':
                self.zipWin(mainfile,zipfilename,allincludes)
            else :
                self.zipUnix(mainfile,zipfilename,allincludes)
    
    
    def zipUnix(self,mainfile,zipfilename,allincludes):
        
        f = ZipFile(zipfilename,"w")
        self.compileTab.SetSelection(Context.COMPILE_RESULT_TAB)
        self.compileLog.Clear()
        self.compileLog.AppendText("Creating bundle zip file :"+zipfilename+"\n")
        f.writestr("README.txt", "")
        f.close()  
        # Main file
        self.compileLog.AppendText("  adding file : "+mainfile)
        try :
             cmd ="zip -j "+zipfilename+" "+mainfile
             os.system(cmd)
        except Exception, err:
            self.compileLog.AppendText(" - Unable to add file : "+str(sys.exc_info()[0]))    
        self.compileLog.AppendText("\n")
         
        # includes
        for inc in allincludes :
            self.compileLog.AppendText("  adding file : "+inc)
            try :
                cmd ="zip -j "+zipfilename+" "+inc
                os.system(cmd)
            except Exception, err:
                self.compileLog.AppendText(" - Unable to add file : "+str(sys.exc_info()[0]))    
            self.compileLog.AppendText("\n")
            
        self.compileLog.AppendText("Completed.\n")
        
                    
    def zipWin(self,mainfile,zipfilename,allincludes):
        maindir = os.path.basename(mainfile).split(".jal")[0]
        f = ZipFile(zipfilename,"w")
        self.compileTab.SetSelection(Context.COMPILE_RESULT_TAB)
        self.compileLog.Clear()
        self.compileLog.AppendText("Creating bundle zip file :"+zipfilename+"\n")
       
        maindir += os.path.sep
       
        # Compiler
        compiler = os.path.expandvars( os.path.expanduser( Context.compiler ) )
        
        if not compiler.endswith(".exe") :
            compiler+=".exe"
        
        destFile = maindir+"compiler"+os.path.sep+os.path.basename(compiler)
        
        self.compileLog.AppendText("  adding file : "+compiler+" as "+destFile)        
        try :
            f.write(compiler,str( destFile ) )
        except Exception, err:
            self.compileLog.AppendText(" - Unable to add file : "+str(sys.exc_info()[0]))    
        self.compileLog.AppendText("\n")
       
       # README.txt
        self.compileLog.AppendText("  adding file : "+maindir+"README.txt")
        try :
            f.writestr(maindir+"README.txt", "compiler"+os.path.sep+os.path.basename(compiler)+" -s lib "+Context.compilerOptions+" "+os.path.basename(mainfile))
        except Exception, err:
            self.compileLog.AppendText(" - Unable to add file : "+str(sys.exc_info()[0]))    
        self.compileLog.AppendText("\n")
            
        # Main file
        destFile = maindir+os.path.basename(mainfile)
        self.compileLog.AppendText("  adding file : "+mainfile+" as "+destFile)
        try :
            f.write(mainfile,str( destFile ) )
        except Exception, err:
            self.compileLog.AppendText(" - Unable to add file : "+str(sys.exc_info()[0]))    
        self.compileLog.AppendText("\n")
        
        # includes
        for inc in allincludes :
            destFile = maindir+"lib"+os.path.sep+os.path.basename(inc)
            self.compileLog.AppendText("  adding file : "+inc+" as "+destFile)
            try :
                # print "basname :" + os.path.basename(inc) + ":"
                f.write(inc,str( destFile ) ) #cp437
                #f.write(inc,os.path.basename(inc)) #cp437
            except Exception, err:
                self.compileLog.AppendText(" - Unable to add file : "+str(sys.exc_info()[0]))    
            self.compileLog.AppendText("\n")
            
        self.compileLog.AppendText("Completed.\n")
        f.close()
        
